`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/11/08 15:56:04
// Design Name: 
// Module Name: uart_tx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module uart_tx#(
    parameter   UART_DATAWIDTH  =   8,
    parameter   UART_CHECK      =   0,
    parameter   UART_STOP_WIDTH =   1
)(
    input                               i_clk           ,
    input                               i_rst           ,
    input  [UART_DATAWIDTH - 1 : 0]     i_user_tx_data  ,
    input                               i_user_tx_valid ,

    output                              o_uart_tx       ,
    output                              o_user_tx_ready 
    );

// /*********parameter**********/

// /*********wire***************/
// wire                            w_tx_active         ;
// /*********reg****************/
// reg [15 : 0]                    r_cnt               ;
// reg [UART_DATAWIDTH - 1 : 0]    r_o_user_tx_data    ;
// reg                             r_tx_check          ;
// reg                             r_o_user_tx_ready   ;
// reg                             r_o_uart_tx         ;

// /*********code***************/
// assign  w_tx_active = r_o_user_tx_ready & i_user_tx_valid;

// always @(posedge i_clk,posedge i_rst ) begin
//     if(i_rst)
//         r_o_user_tx_ready <= 'd1;
//     else if(r_cnt == 1 + UART_DATAWIDTH + UART_STOP_WIDTH +1 && UART_CHECK != 0)
//         r_o_user_tx_ready <= 'd1;
//     else if(r_cnt == 1 + UART_DATAWIDTH + UART_STOP_WIDTH && UART_CHECK == 0)
//         r_o_user_tx_ready <= 'd1;
//     else if(w_tx_active)
//         r_o_user_tx_ready <= 'd0;
//     else
//         r_o_user_tx_ready <= r_o_user_tx_ready;
// end




// always @(posedge i_clk,posedge i_rst ) begin
//     if(i_rst)
//         r_cnt <= 'd0;
//     else if(r_cnt == 1 + UART_DATAWIDTH + UART_STOP_WIDTH +1 && UART_CHECK != 0)
//         r_cnt <= 'd0;
//     else if(r_cnt == 1 + UART_DATAWIDTH + UART_STOP_WIDTH && UART_CHECK == 0)
//         r_cnt <= 'd0;
//     else if(w_tx_active || r_cnt > 0)
//         r_cnt <= r_cnt + 'd1;
// end

// always @(posedge i_clk,posedge i_rst ) begin
//     if(i_rst)
//         r_o_user_tx_data <= 'd0;
//     else if(w_tx_active)
//         r_o_user_tx_data <= i_user_tx_data;
//     else if(r_cnt >= 1 && r_cnt <= UART_DATAWIDTH)
//         r_o_user_tx_data <= r_o_user_tx_data >> 1;
//     else
//         r_o_user_tx_data <= r_o_user_tx_data;
// end

// always @(posedge i_clk,posedge i_rst ) begin
//     if(i_rst)
//         r_tx_check <= 'd0;
//     else if(r_cnt == 1 + UART_DATAWIDTH)
//         r_tx_check <= 'd0;
//     else
//         r_tx_check <= r_tx_check ^ r_o_user_tx_data[0];
// end

// always @(posedge i_clk,posedge i_rst ) begin
//     if(i_rst)
//         r_o_uart_tx <= 1'b1;
//     else if(w_tx_active)
//         r_o_uart_tx <= 1'b0;
//     else if(r_cnt > 1 + UART_DATAWIDTH  -1 && UART_CHECK == 0) // 停止位
//         r_o_uart_tx <= 1'b1;
//     else if(r_cnt > 2 + UART_DATAWIDTH  -1 && UART_CHECK > 0)  // 停止位
//         r_o_uart_tx <= 1'b1;
//     else if(r_cnt > 1 + UART_DATAWIDTH  -1 && UART_CHECK > 0)  // 校验位
//         r_o_uart_tx <= UART_CHECK == 1 ? ~r_tx_check : r_tx_check;
//     else if(r_cnt >= 1 && r_cnt <= UART_DATAWIDTH)             // 数据位
//         r_o_uart_tx <= r_o_user_tx_data[0];
//     else
//         r_o_uart_tx <= 1'b1;
// end

// assign  o_uart_tx       = r_o_uart_tx       ;
// assign  o_user_tx_ready = r_o_user_tx_ready ;
/*************************上面是自己的代码*******************/

/***************function**************/

/***************parameter*************/

/***************port******************/             

/***************mechine***************/

/***************reg*******************/
reg                                 ro_uart_tx          ;
reg                                 ro_user_tx_ready    ;
reg  [15:0]                         r_cnt               ;//计数器位宽高于16bit时，组合逻辑的逻辑级数过高，谨慎使用。
reg  [UART_DATAWIDTH - 1 : 0]    r_tx_data           ;
reg                                 r_tx_check          ;

/***************wire******************/

/***************component*************/

/***************assign****************/
assign o_uart_tx        = ro_uart_tx        ;
assign o_user_tx_ready  = ro_user_tx_ready  ;
assign w_tx_active      = i_user_tx_valid & o_user_tx_ready;

/***************always****************/
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_user_tx_ready <= 'd1;
    else if(w_tx_active)
        ro_user_tx_ready <= 'd0;
    else if(r_cnt == 2 + UART_DATAWIDTH + UART_STOP_WIDTH - 3 && UART_CHECK == 0)
        ro_user_tx_ready <= 'd1;
    else if(r_cnt == 2 + UART_DATAWIDTH + UART_STOP_WIDTH - 2 && UART_CHECK > 0)
        ro_user_tx_ready <= 'd1;
    else 
        ro_user_tx_ready <= ro_user_tx_ready;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_cnt <= 'd0;
    else if(r_cnt == 3 + UART_DATAWIDTH + UART_STOP_WIDTH - 3 && UART_CHECK == 0)
        r_cnt <= 'd0;
    else if(r_cnt == 3 + UART_DATAWIDTH + UART_STOP_WIDTH - 2 && UART_CHECK > 0)
        r_cnt <= 'd0;
    else if(!ro_user_tx_ready)
        r_cnt <= r_cnt + 1;
    else 
        r_cnt <= r_cnt;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_tx_data <= 'd0;
    else if(w_tx_active)
        r_tx_data <= i_user_tx_data;
    else if(!ro_user_tx_ready)
        r_tx_data <= r_tx_data >> 1;
    else 
        r_tx_data <= r_tx_data;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)    
        ro_uart_tx <= 'd1;
    else if(w_tx_active)
        ro_uart_tx <= 'd0;
    else if(r_cnt == 3 + UART_DATAWIDTH - 3 && UART_CHECK > 0)//开启了校验位
        ro_uart_tx <= UART_CHECK == 1 ? ~r_tx_check : r_tx_check;//判断开启的是奇校验还是偶校验
    else if(r_cnt >= 3 + UART_DATAWIDTH - 3 && UART_CHECK == 0)//没有开启校验位，直接发送停止位
        ro_uart_tx <= 'd1;
    else if(r_cnt >= 3 + UART_DATAWIDTH - 2 && UART_CHECK > 0)//开启了校验位，发送完校验位在发送停止位
        ro_uart_tx <= 'd1;
    else if(!ro_user_tx_ready)//发送数据
        ro_uart_tx <= r_tx_data[0];
    else 
        ro_uart_tx <= 'd1;
end

//奇偶算错了
// always@(posedge i_clk,posedge i_rst)
// begin
//     if(i_rst)
//         r_tx_check <= 'd0;
//     else if(!ro_user_tx_ready && UART_CHECK == 1)//odd
//         r_tx_check <= ~(r_tx_check ^ ro_uart_tx);
//     else if(!ro_user_tx_ready && UART_CHECK == 2)//even
//         r_tx_check <= r_tx_check ^ ro_uart_tx;
//     else 
//         r_tx_check <= 'd0;
// end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_tx_check <= 'd0;
    else if(r_cnt == 3 + UART_DATAWIDTH - 3)
        r_tx_check <= 'd0;
    else 
        r_tx_check <= r_tx_check ^ r_tx_data[0];
end
endmodule
